package com.woniu.mealsService.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.Page;
import com.woniu.dto.StoreListDTO;
import com.woniu.dto.StoreProductDTO;
import com.woniu.exception.meals.StoreException;
import com.woniu.form.ProductForm;
import com.woniu.mealsService.model.Product;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.form.StoreProductListForm;
import com.woniu.mealsService.model.FoodType;
import com.woniu.mealsService.model.Store;
import com.woniu.mealsService.model.StoreProduct;
import com.woniu.mealsService.mapper.StoreProductMapper;
import com.woniu.mealsService.service.OrderProductService;
import com.woniu.mealsService.service.FoodTypeService;
import com.woniu.mealsService.service.StoreFileUploadService;
import com.woniu.mealsService.service.StoreProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.mealsService.service.StoreService;
import com.woniu.mealsService.util.Data;
import com.woniu.param.PageParam;
import com.woniu.param.UpdateDiscountParam;
import com.woniu.server.RedisUtil;
import com.woniu.param.*;
import com.woniu.server.RedisKey;
import com.woniu.server.RedisUtil;
import com.woniu.utils.EnumException;
import com.woniu.utils.EnumException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 店铺菜品表 服务实现类
 * </p>
 *
 * @author jiang
 * @since 2024年12月10日
 */
@Service
public class StoreProductServiceImpl extends ServiceImpl<StoreProductMapper, StoreProduct> implements StoreProductService {
    @Autowired
    private StoreProductMapper storeProductMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private StoreService storeService;
    @Autowired
    private FoodTypeService foodTypeService;
    @Autowired
    private StoreFileUploadService storeFileUploadService;
    /**
     * 更新产品折扣信息
     * 此方法用于根据提供的参数更新商店产品的折扣信息确保折扣值小于等于1，
     * 并且更新操作由特定用户执行如果商品不存在或折扣信息不合法，将抛出异常
     *
     * @param param 更新折扣的参数，包含需要更新的折扣信息
     * @param userId 执行更新操作的用户ID，用于记录是谁进行了更新操作
     * @throws RuntimeException 如果折扣大于1或更新的商品不存在，抛出运行时异常
     */
    @Override
    public void updateDiscount(UpdateDiscountParam param, String userId) {
        // 将更新折扣参数转换为商店产品对象，便于后续操作
        StoreProduct storeProduct = BeanUtil.toBean(param, StoreProduct.class);
        // 检查折扣是否大于1，如果大于1，则抛出异常，因为折扣信息不合法
        if(storeProduct.getDiscount()>1){
            throw new RuntimeException("折扣信息异常");
        }
        // 设置更改用户ID，记录是谁进行了更新操作
        storeProduct.setChangeUser(userId);
        // 设置更新时间，记录更新时间
        storeProduct.setUpdateTime(LocalDateTime.now());
        // 根据用户id查询商品信息
        storeProduct.setUserId(userId);
        // 调用mapper方法更新数据库中的产品折扣信息
        Integer count = storeProductMapper.updateDiscount(storeProduct);
        // 如果更新影响的行数为0，说明商品不存在，抛出异常
        if(count==0){
            throw new RuntimeException("商品不存在");
        }
    }

    /**
     * 重写搜索店铺商品列表的方法
     *
     * @param userId 用户ID，用于确定是否为特定用户查询
     * @param param 包含分页和查询参数的对象，用于搜索商品列表
     * @return 返回分页后的商品列表信息
     */
    @Override
    public PageInfo<StoreProductDTO> searchStoreProductList(String userId, StoreProductListParam param) {
        System.out.println("param:"+param.getPageNum()+","+param.getPageSize());


        // 将查询参数对象转换为店铺商品对象
        StoreProduct storeProduct = BeanUtil.toBean(param, StoreProduct.class);

        // 根据用户ID调整商品状态查询条件
        if (userId == null) {
            // 如果用户ID为空，只查询上架的商品
            storeProduct.setStoreProductState(Data.STORE_PRODUCT_PUT_ON);
        } else {
            // 根据用户ID获取店铺信息
            Store store = storeService.getOne(new QueryWrapper<Store>().eq("user_id", userId));

            // 如果店铺不存在或与查询参数中的店铺ID不匹配，只查询上架的商品
            if (store == null || !Long.valueOf(param.getStoreId()).equals(store.getStoreId())) {
                storeProduct.setStoreProductState(Data.STORE_PRODUCT_PUT_ON);
            }
        }
        // 分页
        Page<StoreProduct> objects = PageHelper.startPage(param.getPageNum(), param.getPageSize());
        // 执行商品列表查询
        List<StoreProductDTO> storeProducts = storeProductMapper.searchStoreProductList(storeProduct);

        // 返回分页后的商品列表信息
        return new PageInfo<>(storeProducts);
    }

    /**
     * 根据参数查询所有产品列表
     *
     * @param param 查询参数，包括页码和页面大小等信息
     * @return 返回一个包含产品信息的PageInfo对象
     */
    @Override
    public PageInfo<StoreProductDTO> searchAllProductList(AllProductListParam param) {
        // 启用分页功能，根据传入的页码和页面大小进行设置
        PageHelper.startPage(param.getPageNum(), param.getPageSize());

        // 将查询参数转换为StoreProduct对象，便于后续查询
        StoreProduct storeProduct = BeanUtil.toBean(param, StoreProduct.class);

        // 设置产品状态为上架状态，确保只查询出可销售的产品
        storeProduct.setStoreProductState(Data.STORE_PRODUCT_PUT_ON);

        // 执行查询，并将结果封装到PageInfo对象中返回
        return new PageInfo<>(storeProductMapper.searchStoreProductList(storeProduct));
    }

    /**
     * 根据店铺ID搜索店铺内打折产品列表
     *
     * @param storeId 店铺ID，用于指定查询哪个店铺的产品
     * @param PageNum 页码，用于分页查询
     * @param PageSize 每页大小，用于分页查询
     * @return 返回包含打折产品列表的PageInfo对象
     */
    @Override
    public PageInfo<StoreProductDTO> searchStoreDiscountProductList(String storeId, Integer PageNum, Integer PageSize) {
        // 开始分页，传入页码和每页大小
        PageHelper.startPage(PageNum, PageSize);
        // 调用Mapper方法，搜索店铺内所有打折产品
        List<StoreProductDTO> storeProducts = storeProductMapper.searchDiscountProductList(storeId);
        // 将查询结果封装到PageInfo对象中并返回
        return new PageInfo<>(storeProducts);
    }

    /**
     * 重写搜索所有折扣商品列表的方法
     *
     * @param param 分页参数，包含页码和每页大小
     * @return 返回一个包含StoreProduct对象的PageInfo对象，代表分页后的折扣商品列表
     */
    @Override
    public PageInfo<StoreProductDTO> searchAllDiscountProductList(PageParam param) {
        // 开始分页，依据传入的页码和每页大小
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        // 调用Mapper方法获取折扣商品列表，传入null表示不进行任何条件筛选
        List<StoreProductDTO> storeProducts = storeProductMapper.searchDiscountProductList(null);
        // 创建并返回一个包含分页数据的PageInfo对象
        return new PageInfo<>(storeProducts);
    }


    /**
     * 上架商品
     *
     * @param productId 商品ID
     * @param userId 用户ID
     *
     * 该方法用于将指定的商品上架到店铺中它创建一个StoreProduct对象，设置商品ID、用户ID、商品状态为“已上架”，
     * 以及修改用户和更新时间然后尝试更新数据库中的商品状态如果更新失败（即商品不存在），则抛出运行时异常
     *
     * 注意：此处无需返回值，因为方法的目的是执行一个上架操作，而不是计算或返回任何结果
     * 抛出“商品不存在”异常是为了通知调用者商品上架失败的原因
     */
    @Override
    public void putOn(Long productId, String userId) {
        // 创建StoreProduct对象并设置商品上架所需的基本信息
        StoreProduct storeProduct = new StoreProduct();
        storeProduct.setStoreProductId(productId);
        storeProduct.setUserId(userId);
        storeProduct.setStoreProductState(Data.STORE_PRODUCT_PUT_ON);
        storeProduct.setChangeUser(userId);
        storeProduct.setUpdateTime(LocalDateTime.now());

        // 尝试更新数据库中商品的状态
        Integer count = storeProductMapper.updateStateById(storeProduct);

        // 如果更新失败，抛出异常表示商品不存在
        if(count==0){
            throw new RuntimeException("商品不存在或已上架");
        }
    }

    /**
     * 下架指定的商品
     *
     * @param productId 商品ID，用于标识要下架的商品
     * @param userId 用户ID，表示执行下架操作的用户
     * @throws RuntimeException 如果商品不存在，则抛出运行时异常
     */
    @Override
    public void putOff(Long productId, String userId) {
        // 创建一个StoreProduct对象，用于存储商品信息
        StoreProduct storeProduct = new StoreProduct();

        // 设置商品ID
        storeProduct.setStoreProductId(productId);
        // 设置用户ID
        storeProduct.setUserId(userId);
        // 设置商品状态为已下架
        storeProduct.setStoreProductState(Data.STORE_PRODUCT_PUT_OFF);
        // 设置修改用户ID
        storeProduct.setChangeUser(userId);
        // 设置修改时间
        storeProduct.setUpdateTime(LocalDateTime.now());

        // 调用Mapper方法更新商品状态
        Integer count = storeProductMapper.updateStateById(storeProduct);

        // 如果更新影响的行数为0，说明商品不存在，抛出异常
        if(count==0){
            throw new RuntimeException("商品不存在或已下架");
        }
    }
    /**
     * 删除商品
     *
     * @param productId 商品ID，用于标识要删除的商品
     * @param userId 用户ID，记录删除商品的操作者
     *
     * 该方法通过创建一个StoreProduct对象并设置相关属性来删除指定的商品
     * 如果删除操作影响的记录数为0，则抛出异常，表明商品不存在
     */
    @Override
    public void deleteProduct(Long productId, String userId) {
        // 创建StoreProduct对象，并设置商品ID和用户ID
        StoreProduct storeProduct = new StoreProduct();
        storeProduct.setStoreProductId(productId);
        storeProduct.setUserId(userId);
        // 标记商品为删除状态
        storeProduct.setProductDel(Data.STORE_PRODUCT_DELETE);
        // 记录删除操作的用户
        storeProduct.setChangeUser(userId);
        // 设置删除操作的时间
        storeProduct.setUpdateTime(LocalDateTime.now());
        // 调用Mapper方法执行删除操作
        Integer count = storeProductMapper.deleteProduct(storeProduct);
        // 如果删除操作未成功，抛出异常
        if(count==0){
            throw new RuntimeException("商品不存在");
        }
    }

    /**
     * 添加商户商品信息
     *
     * @param param 商户商品插入参数，包含商品名称、商品介绍、食品类型ID和商品价格等信息
     * @param userId 用户ID，用于关联商户信息
     *
     * 此方法主要用于商户添加新的商品信息到系统中它首先根据用户ID查找对应的商户信息，
     * 如果商户不存在，则抛出运行时异常接着创建一个新的StoreProduct对象，填充其属性，
     * 包括商品名称、介绍、用户ID、商户ID、商户名称、创建时间等然后检查食品类型是否存在，
     * 如果不存在，则抛出运行时异常最后，将商品信息插入数据库，并绑定商品图片
     */
    @Override
    @Transactional
    public void addStoreProduct(InsertStoreProductParam param, String userId) {
        // 根据用户ID查询商户信息
        Store store = storeService.getOne(new QueryWrapper<Store>().eq("user_id", userId));
        if (store==null){
            throw new RuntimeException("商户不存在");
        }

        StoreProduct storeProduct = new StoreProduct();
        storeProduct.setProductName(param.getProductName());
        storeProduct.setProductIntr(param.getProductIntr());
        storeProduct.setUserId(userId);
        storeProduct.setStoreId(store.getStoreId().toString());
        storeProduct.setStoreName(store.getStoreName());
        storeProduct.setCreateTime(LocalDateTime.now());

        // 根据食品类型ID查询食品类型信息
        FoodType foodType = foodTypeService.searchFoodTypeById(param.getFoodTypeId());
        if (foodType == null){
            throw new RuntimeException("商品类型不存在");
        }
        if(!foodType.getStoreId().equals(String.valueOf(store.getStoreId()))){
            throw new RuntimeException("不是该菜品类型创建者，无法使用该菜品类型");
        }

        storeProduct.setFoodTypeId(param.getFoodTypeId());
        storeProduct.setFoodTypeName(foodType.getFoodTypeName());
        storeProduct.setPrice(param.getProductPrice());
        storeProduct.setProductDel(Data.STORE_PRODUCT_NOT_DELETE);
        storeProduct.setStoreProductState(Data.STORE_PRODUCT_PUT_OFF);

        // 插入商品信息到数据库
        storeProductMapper.insert(storeProduct);

        // 绑定图片表id
        if (param.getFilePath()!=null){
            storeFileUploadService.bindFileUploadId(storeProduct.getStoreProductId(), param.getFilePath());
        }
    }

    /**
     * 更新商店商品信息
     *
     * @param param 更新商店商品的参数，包含需要更新的商品信息
     * @param userId 用户ID，用于记录最后一次修改商品信息的用户
     *
     * 此方法首先将更新参数转换为StoreProduct对象，然后设置修改用户和修改时间，
     * 最后调用Mapper层的方法更新数据库中的商品信息如果商品不存在，则抛出运行时异常
     */
    @Override
    public void updateStoreProduct(UpdateStoreProductParam param, String userId) {

        // 将更新参数转换为StoreProduct对象
        StoreProduct storeProduct = BeanUtil.toBean(param, StoreProduct.class);
        Store storeServiceOne = storeService.getOne(new LambdaQueryWrapper<Store>().eq(Store::getUserId, userId));
        if (storeServiceOne==null){
            throw new RuntimeException("商户不存在");
        }
        // 如果食品类型ID不为空，则获取并设置食品类型名称
        if (storeProduct.getFoodTypeId()!=null){
            FoodType foodType = foodTypeService.searchFoodTypeById(storeProduct.getFoodTypeId());
            if (foodType==null){
                throw new RuntimeException("商品类型不存在");
            }
            if (!foodType.getStoreId().equals(String.valueOf(storeServiceOne.getStoreId()))){
                throw new RuntimeException("不是该菜品类型创建者，无法使用该菜品类型");
            }
            storeProduct.setFoodTypeName(foodType.getFoodTypeName());
        }
        // 设置修改用户
        storeProduct.setChangeUser(userId);
        // 设置修改时间
        storeProduct.setUpdateTime(LocalDateTime.now());
        // 限定用户
        storeProduct.setUserId(userId);
        // 更新数据库中的商品信息
        Integer count = storeProductMapper.updateStoreProduct(storeProduct);
        // 如果更新影响的行数为0，说明商品不存在，抛出异常
        if(count==0){
            throw new RuntimeException("商品不存在");
        }
    }

    /**
     * 根据产品ID搜索商店产品详情
     * 此方法用于获取特定产品的详细信息，以便在用户界面上展示详细的产品信息
     * 它通过调用storeProductMapper中的相应方法来实现
     *
     * @param productId 产品ID，用于标识特定的产品
     * @return StoreProduct 包含产品详细信息的StoreProduct对象
     */
    @Override
    public StoreProductDTO searchStoreProductDetail(String productId) {
        StoreProductDTO storeProduct = storeProductMapper.searchStoreProductDetail(productId);
        // 如果获取的对象为空，说明商品不存在，抛出异常
        if (storeProduct==null){
            throw new RuntimeException("商品不存在");
        }
        return storeProduct;
    }
    //购物车

    /**
     * 添加商品到购物车
     *
     * @param productId 商品ID，不能为空
     * @param userId 用户ID，不能为空
     * @param num 商品数量，必须大于0
     * @throws IllegalArgumentException 如果参数不合法，则抛出此异常
     */
    @Override
    public void addCart(String productId, String userId, Integer num) {
        // 检验参数合法性
        if (productId == null || userId == null || num == null || num <= 0) {
            throw new IllegalArgumentException("参数不合法");
        }

        // 查询商品详情
        StoreProductDTO storeProduct = searchStoreProductDetail(productId);
        // 商品不存在
        if (storeProduct == null) {
            throw new IllegalArgumentException("商品不存在");
        }
        // 商品已下架
        if (storeProduct.getStoreProductState() != Data.STORE_PRODUCT_PUT_ON) {
            throw new IllegalArgumentException("商品已下架");
        }
        // 商品已删除
        if (storeProduct.getProductDel() == Data.STORE_PRODUCT_DELETE) {
            throw new IllegalArgumentException("商品已删除");
        }

        // 获取店铺ID
        String storeId = storeProduct.getStoreId();
        // 构造购物车键
        String cartKey = RedisKey.shoppingCart(userId, storeId);

        // 从 Redis 查询用户的购物车店铺集合
        Set<String> storeSet = redisUtil.getSet(RedisKey.shoppingCarts(userId));

        // 判断店铺是否存在于用户购物车中
        if (storeSet == null || !storeSet.contains(storeId)) {
            // 添加店铺 ID 到集合
            redisUtil.addSet(RedisKey.shoppingCarts(userId), storeId);

            // 创建新的购物车数据
            Map<Object, Object> cart = new HashMap<>();
            Map<String, Object> productDetailMap = new HashMap<>();
            productDetailMap.put("productId", productId);
            productDetailMap.put("num", num);
            cart.put(productId, JSONUtil.toJsonStr(productDetailMap));

            // 保存到 Redis
            redisUtil.addHash(cartKey, cart);
        } else {
            // 获取当前店铺的购物车
            Map<Object, Object> cart = redisUtil.getAllHash(cartKey);

            if (cart == null) {
                cart = new HashMap<>();
            }

            // 判断商品是否已存在
            String productDetail = (String) cart.get(productId);
            Map<String, Object> productDetailMap;
            if (productDetail != null) {
                // 商品已存在，更新数量
                productDetailMap = JSONUtil.toBean(productDetail, Map.class);
                int existingNum = Integer.parseInt(productDetailMap.get("num").toString());
                productDetailMap.put("num", existingNum + num);
            } else {
                // 新增商品
                productDetailMap = new HashMap<>();
                productDetailMap.put("productId", productId);
                productDetailMap.put("num", num);
            }
            cart.put(productId, JSONUtil.toJsonStr(productDetailMap));

            // 保存到 Redis
            redisUtil.addHash(cartKey, cart);
        }
    }


    /**
     * 根据用户ID搜索购物车信息
     *
     * @param userId 用户ID，用于识别用户的购物车信息
     * @return 返回一个列表，每个元素是一个映射，包含每个店铺的购物车详情
     * @throws IllegalArgumentException 如果购物车为空，则抛出此异常
     */
    @Override
    public List<Map<String,Object>> searchCarts(String userId) {
        // 获取用户购物车的所有店铺 ID
        Set<String> storeSet = redisUtil.getSet(RedisKey.shoppingCarts(userId));
        if (storeSet == null || storeSet.isEmpty()) {
            throw new IllegalArgumentException("购物车为空");
        }

        List<Map<String, Object>> cartByStoreList = new ArrayList<>();

        // 遍历店铺 ID，获取每个店铺的购物车
        for (String storeId : storeSet) {
            //创建店铺总价计数器
            BigDecimal totalPrice = new BigDecimal(0);
            //创建店铺总数计数器
            Integer totalNum = 0;
            //获取店铺购物车key
            String cartKey = RedisKey.shoppingCart(userId, storeId);
            // 获取店铺对应的购物车数据
            Map<Object, Object> cart = redisUtil.getAllHash(cartKey);

            if (cart != null && !cart.isEmpty()) {
                List<Map<String, Object>> productList = new ArrayList<>();
                for (Map.Entry<Object, Object> entry : cart.entrySet()) {
                    String productDetailJson = (String) entry.getValue();
                    Map<String, Object> productDetail = JSONUtil.toBean(productDetailJson, Map.class);
                    StoreProductDTO storeProduct = storeProductMapper.searchStoreProductDetail(productDetail.get("productId").toString());
                    productDetail.put("productName", storeProduct.getProductName());
                    productDetail.put("originalPrice", storeProduct.getPrice().multiply(BigDecimal.valueOf((Integer) productDetail.get("num"))));
                    BigDecimal discountedPrice = storeProduct.getPrice().multiply(BigDecimal.valueOf(storeProduct.getDiscount()).multiply(BigDecimal.valueOf((Integer) productDetail.get("num"))));
                    totalPrice = totalPrice.add(discountedPrice);
                    totalNum += (Integer) productDetail.get("num");
                    productDetail.put("discountedPrice", discountedPrice);
                    productList.add(productDetail);
                }

                // 构造店铺的购物车数据
                Map<String, Object> storeCart = new HashMap<>();
                storeCart.put("storeId", storeId);
                storeCart.put("totalPrice", totalPrice);
                storeCart.put("totalNum", totalNum);
                storeCart.put("products", productList);
                cartByStoreList.add(storeCart);
            }
        }

        if (cartByStoreList.isEmpty()) {
            throw new IllegalArgumentException("购物车为空");
        }

        return cartByStoreList;
    }

    /**
     * 根据用户ID和店铺ID搜索购物车
     *
     * @param userId 用户ID，用于识别用户
     * @param storeId 店铺ID，用于识别店铺
     * @return 返回包含店铺购物车信息的Map对象，包括店铺ID、总价、总数和商品列表
     */
    @Override
    public Map<String, Object> searchCartByStoreId(String userId, String storeId) {
        // 从Redis中获取用户和店铺对应的购物车数据
        Map<Object, Object> cart = redisUtil.getAllHash(RedisKey.shoppingCart(userId, storeId));
        List<Map<String, Object>> productList = new ArrayList<>();
        // 创建店铺总价计数器
        BigDecimal totalPrice = new BigDecimal(0);
        // 创建店铺总数计数器
        Integer totalNum = 0;
        for (Map.Entry<Object, Object> entry : cart.entrySet()){
            String productDetailJson = (String) entry.getValue();
            // 将购物车中的商品详情JSON字符串转换为Map对象
            Map<String, Object> productDetail = JSONUtil.toBean(productDetailJson, Map.class);
            // 根据商品ID查询商品详细信息
            StoreProductDTO storeProduct = storeProductMapper.searchStoreProductDetail(productDetail.get("productId").toString());
            // 计算商品原价总和
            productDetail.put("productName", storeProduct.getProductName());
            productDetail.put("originalPrice", storeProduct.getPrice().multiply(BigDecimal.valueOf((Integer) productDetail.get("num"))));
            // 计算商品折后价总和
            BigDecimal discountedPrice = storeProduct.getPrice().multiply(BigDecimal.valueOf(storeProduct.getDiscount()).multiply(BigDecimal.valueOf((Integer) productDetail.get("num"))));
            totalPrice = totalPrice.add(discountedPrice);
            // 累加商品数量
            totalNum += (Integer) productDetail.get("num");
            productDetail.put("discountedPrice", discountedPrice);
            productList.add(productDetail);
        }

        // 构造店铺的购物车数据
        Map<String, Object> storeCart = new HashMap<>();
        storeCart.put("storeId", storeId);
        storeCart.put("totalPrice", totalPrice);
        storeCart.put("totalNum", totalNum);
        storeCart.put("products", productList);
        return storeCart;
    }

    /**
     * 清空购物车
     *
     * @param userId 用户ID，用于标识用户的购物车
     * @param storeId 商店ID，用于指定用户在特定商店的购物车
     */
    @Override
    public void clearCart(String userId, String storeId) {
        // 删除指定用户和商店的购物车详情键
        redisUtil.delete(RedisKey.shoppingCart(userId, storeId));
        // 从用户的所有购物车集合中移除指定的商店ID
        redisUtil.removeSet(RedisKey.shoppingCarts(userId), storeId);
    }

    /**
     * 从购物车中移除指定数量的商品
     * 如果商品不存在、购物车为空或购物车中不存在该商品，则抛出异常
     *
     * @param userId 用户ID，用于标识购物车的主人
     * @param productId 商品ID，用于指定要移除的商品
     * @param num 要从购物车中移除的商品数量
     * @throws IllegalArgumentException 如果商品不存在、购物车为空或购物车中不存在该商品
     */
    @Override
    public void removeCart(String userId, String productId, Integer num) {
        // 根据商品ID搜索商品详细信息
        StoreProductDTO storeProduct = searchStoreProductDetail(productId);
        // 如果商品不存在，抛出异常
        if (storeProduct == null) {
            throw new IllegalArgumentException("商品不存在");
        }

        // 获取用户购物车中的所有商品
        Map<Object, Object> productList = redisUtil.getAllHash(RedisKey.shoppingCart(userId, storeProduct.getStoreId()));
        // 如果购物车为空，抛出异常
        if (productList == null || productList.isEmpty()) {
            throw new IllegalArgumentException("购物车为空");
        }

        // 检查购物车中是否包含指定的商品
        if (productList.containsKey(productId)) {
            // 获取商品详细信息的JSON字符串
            String productDetailJson = (String) productList.get(productId);
            // 将JSON字符串转换为Map对象
            Map<String, Object> productDetail = JSONUtil.toBean(productDetailJson, Map.class);
            // 获取购物车中该商品的现有数量
            int existingNum = Integer.parseInt(productDetail.get("num").toString());

            // 如果要移除的数量等于或超过购物车中的数量，从购物车中移除该商品
            if (existingNum <= num) {
                redisUtil.removeHash(RedisKey.shoppingCart(userId, storeProduct.getStoreId()), productId);
                // 如果移除商品后购物车为空，删除购物车对应的哈希表和购物车集合中的相应条目
                if (redisUtil.getAllHash(RedisKey.shoppingCart(userId, storeProduct.getStoreId())).isEmpty()) {
                    redisUtil.delete(RedisKey.shoppingCart(userId, storeProduct.getStoreId()));
                    redisUtil.removeSet(RedisKey.shoppingCarts(userId), storeProduct.getStoreId());
                }
            } else {
                // 如果要移除的数量小于购物车中的数量，更新购物车中该商品的数量
                productDetail.put("num", existingNum - num);
                redisUtil.addHash(RedisKey.shoppingCart(userId, storeProduct.getStoreId()), productId, JSONUtil.toJsonStr(productDetail));
            }
        } else {
            // 如果购物车中不存在该商品，抛出异常
            throw new IllegalArgumentException("购物车中不存在该商品");
        }
    }

    /**
     * 计算购物车中所有产品的总价格
     * 此方法首先检查传入的购物车列表是否非空且不为null，然后通过产品ID收集对应的商店产品信息，
     * 并根据产品价格、折扣和数量计算总价格
     *
     * @param cartList 购物车列表，包含产品表单信息
     * @return 返回购物车中所有产品的总价格如果购物车列表为空或为null，则返回0.0
     */
    @Override
    public Double getTotalPrice(List<ProductForm> cartList) throws Exception{
        // 检查购物车列表是否非空且不为null
        if (cartList != null && !cartList.isEmpty()) {
            // 将购物车列表中的产品ID转换为Long类型并收集到列表中
            List<Long> collect = cartList.stream().map(o -> Long.parseLong(o.getProductId())).collect(Collectors.toList());
            // 根据转换后的产品ID列表获取商店产品列表
            List <StoreProduct> storeProductList =storeProductMapper.List(collect);
            List<StoreProduct> collect1 = storeProductList.stream().filter(o -> o.getStoreProductState() == 0).collect(Collectors.toList());
            if (collect1.size()!=storeProductList.size()){
                throw new StoreException(EnumException.STORE_PRODUCT_STATE_EXCEPTION);
            }
            // 初始化总价格为0.0
            BigDecimal totalPrice = new BigDecimal("0.0");
            // 遍历商店产品列表
            for (StoreProduct storeProduct : storeProductList) {
                // 遍历购物车列表
                for (ProductForm productForm : cartList) {
                    // 比较购物车中的产品ID与商店产品ID是否匹配
                    if (Long.valueOf(productForm.getProductId()).compareTo(storeProduct.getStoreProductId())==0){
                        // 计算单个产品的价格（考虑折扣和数量）并累加到总价格中
                        BigDecimal multiply = storeProduct.getPrice().multiply(BigDecimal.valueOf(storeProduct.getDiscount())).multiply(BigDecimal.valueOf(Integer.parseInt(productForm.getCount())));
                        totalPrice = totalPrice.add(multiply);
                    }
                }
            }
            // 返回计算得到的总价格的double值
            return totalPrice.doubleValue();
        }
        // 如果购物车列表为空或为null，返回0.0
        return 0.0;
    }


    //根据菜品名称模糊查询拥有该菜品的店铺
    /**
     * 根据产品名称搜索店铺
     *
     * @param productName 产品名称，用于搜索相关店铺
     * @param pageNum 分页参数，指定返回的页码
     * @param pageSize 分页参数，每页返回的记录数
     * @return 返回包含店铺信息的PageInfo对象
     */
    @Override
    public PageInfo<StoreListDTO> searchStoreByProductName(String productName,Integer pageNum,Integer pageSize) {
        // 启用分页功能，根据传入的页码和每页大小进行设置
        PageHelper.startPage(pageNum, pageSize);
        // 调用mapper方法，根据产品名称搜索店铺
        List<StoreListDTO> stores = storeProductMapper.searchStoreByProductName(productName);
        // 将搜索结果封装到PageInfo对象中并返回
        return new PageInfo<>(stores);
    }
}
